package com.happy.qademo.websheet.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;




@Controller
public class FileUploadController {
   private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class);

    //处理文件上传
    @RequestMapping("/uploadfile")
    public String uploadFile(@RequestParam(value = "file", required = false) MultipartFile file, @RequestParam(value = "uploadPath", required = false) String uploadPathParam, Model model) {
        
         // 获取用户目录
         String userDir = System.getProperty("user.dir");
         if (userDir == null) {
             model.addAttribute("message", "无法获取用户目录");
             return "file-list";
         }
         
         String uploadPath;
         if (uploadPathParam != null && !uploadPathParam.isEmpty()) {
            uploadPathParam = uploadPathParam.trim();
             File pathFile = new File(uploadPathParam);
             if (pathFile.isAbsolute()) {
                 // 是绝对路径，使用原样路径
                 uploadPath = uploadPathParam.trim();
             } else {
                 // 不是绝对路径，在 uploads 下面创建子目录
                 uploadPath = userDir + File.separator + "uploads" + File.separator + uploadPathParam.trim();
             }
         } else {
             // 不传参数，直接放在 uploads 下
             uploadPath = userDir + File.separator + "uploads";
         }
 
         // 创建上传目录（如果不存在）
         File uploadDir = new File(uploadPath);
         if (!uploadDir.exists()) {
             if (!uploadDir.mkdirs()) {
                 model.addAttribute("message", "无法创建上传目录: " + uploadPath);
                 return "file-list";
             }
         }
 
        // 标准化路径，去除多余分隔符等
        uploadPath = new File(uploadPath).getAbsolutePath();
        
        File directory = new File(uploadPath);
        if (!directory.exists()) {
            if (directory.mkdirs()) {
                System.out.println("uploads 目录创建成功");
            } else {
                System.err.println("无法创建 uploads 目录");
                model.addAttribute("message", "无法创建 uploads 目录");
                return "file-list";
            }
        }
        File directory_yuan = new File( userDir + File.separator + "uploads");
        File[] files = directory_yuan.listFiles();
        if (files != null) {
            List<File> fileList = Arrays.asList(files);
            model.addAttribute("files", fileList);
        }

        if (file == null || file.isEmpty()) {
            model.addAttribute("message", "请选择一个文件进行上传");
            return "file-list";
        }

        // 获取文件名，处理可能的 null 值
        String fileName = file.getOriginalFilename();
        if (fileName == null) {
            model.addAttribute("uploadmessage", "无法获取文件名，文件上传失败");
            return "file-list";
        }

        try {
            byte[] bytes = file.getBytes();
            Path path = Paths.get(uploadPath + File.separator + fileName);
            Files.write(path, bytes);
            model.addAttribute("uploadmessage", "文件 " + fileName + " 上传成功,存放路径是：" + uploadPath);
        } catch (IOException e) {
            e.printStackTrace();
            model.addAttribute("uploadmessage", "文件上传失败");
        }

        return "file-list";
    }

      //处理文件上传api
      @ResponseBody
      @RequestMapping("/uploadfileapi")
      public String uploadFileApi(@RequestParam(value = "file", required = false) MultipartFile file,@RequestParam(value = "uploadPath", required = false) String uploadPathParam) {
        // 获取用户目录
        String userDir = System.getProperty("user.dir");
        if (userDir == null) {
            return "无法获取用户目录";
        }

        String uploadPath;
        if (uploadPathParam != null && !uploadPathParam.isEmpty()) {
            File pathFile = new File(uploadPathParam);
            if (pathFile.isAbsolute()) {
                // 是绝对路径，使用原样路径
                uploadPath = uploadPathParam;
            } else {
                // 不是绝对路径，在 uploads 下面创建子目录
                uploadPath = userDir + File.separator + "uploads" + File.separator + uploadPathParam;
            }
        } else {
            // 不传参数，直接放在 uploads 下
            uploadPath = userDir + File.separator + "uploads";
        }

        // 标准化路径，去除多余分隔符等
        uploadPath = new File(uploadPath).getAbsolutePath();

          File directory = new File(uploadPath);
          if (!directory.exists()) {
              if (directory.mkdirs()) {
                  System.out.println("uploads 目录创建成功");
              } else {
                  System.err.println("无法创建 uploads 目录");
                  return "无法创建 uploads 目录";
              }
            }
          if (file == null || file.isEmpty()) {
              return "请选择一个文件进行上传";
            }
  
          // 获取文件名，处理可能的 null 值
          String fileName = file.getOriginalFilename();
          if (fileName == null) {
              return "无法获取文件名，文件上传失败";
            }
          try {
              byte[] bytes = file.getBytes();
              Path path = Paths.get(uploadPath + File.separator + fileName);
              Files.write(path, bytes);
              return "文件 " + fileName + " 上传成功,存放路径是：" + uploadPath;
          } catch (IOException e) {
              e.printStackTrace();
              return "文件 " + fileName +"上传失败";
          }
      }

    // @GetMapping("/downloadfile/{filename}")
    // public ResponseEntity<Resource> downloadFile(@PathVariable String filename) {
    //     // 文件存储在当前目录下的 uploads 文件夹中
    //     String uploadPath = System.getProperty("user.dir") + File.separator + "uploads";
    //     File file = new File(uploadPath+"/" + filename);
    //     Resource resource = new FileSystemResource(file);

    //     HttpHeaders headers = new HttpHeaders();
    //     headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);

    //     return ResponseEntity.ok()
    //            .headers(headers)
    //            .contentLength(file.length())
    //            .contentType(MediaType.APPLICATION_OCTET_STREAM)
    //            .body(resource);
    // }



    // @GetMapping("/downloadfile/{filePath:.+}")
    // public ResponseEntity<Resource> downloadFile(@PathVariable String filePath) {
    //     // 文件存储在当前目录下的 uploads 文件夹中
    //     String uploadPath = System.getProperty("user.dir") + File.separator + "uploads";
       
    //     // 防止路径遍历攻击
    //     File safeFile = getSafeFile(uploadPath, filePath);
    //     if (safeFile == null ||!safeFile.exists() ||!safeFile.isFile()) {
    //         return ResponseEntity.notFound().build();
    //     }

    //     Resource resource = new FileSystemResource(safeFile);

    //     HttpHeaders headers = new HttpHeaders();
    //     String filename = safeFile.getName();
    //     headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);

    //     return ResponseEntity.ok()
    //            .headers(headers)
    //            .contentLength(safeFile.length())
    //            .contentType(MediaType.APPLICATION_OCTET_STREAM)
    //            .body(resource);
    // }

    private File getSafeFile(String basePath, String filePath) {
        try {
            File baseDir = new File(basePath);
            File requestedFile = new File(baseDir, filePath);
            if (requestedFile.getCanonicalPath().startsWith(baseDir.getCanonicalPath())) {
                return requestedFile;
            }
        } catch (Exception e) {
            // 处理异常，这里简单返回 null
            return null;
        }
        return null;
    }
    @GetMapping("/downloadfile/**")
    public Object downloadFile(HttpServletRequest request, Model model) {
        // 从请求中获取完整的请求路径
        String fullPath = request.getRequestURI();
        // 去除 "/downloadfile/" 前缀以得到实际的 filePath
        String filePath = fullPath.substring("/downloadfile/".length());
        try {
                filePath = URLDecoder.decode(filePath, "UTF-8");
            } catch (java.io.UnsupportedEncodingException e) {
                // 处理不支持的编码异常
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        // 文件存储在当前目录下的 uploads 文件夹中
        String uploadPath = System.getProperty("user.dir") + File.separator + "uploads";
        
        // 防止路径遍历攻击
        File safeFile = getSafeFile(uploadPath, filePath);
        if (safeFile == null) {
            return ResponseEntity.notFound().build();
        }

        if (safeFile.isDirectory()) {
            // 处理 directory.listFiles() 可能返回 null 的情况
            File[] files = safeFile.listFiles();
            if (files != null) {
                List<File> fileList = Arrays.asList(files);
                // 确保使用 "files" 作为变量名添加到 Model 中
                model.addAttribute("files", fileList);
            }
            return "otherfilelist";
        } else if (safeFile.isFile()) {
            Resource resource = new FileSystemResource(safeFile);
            HttpHeaders headers = new HttpHeaders();
            String filename = safeFile.getName();
            try {
            // 对文件名进行 UTF-8 编码
            String encodedFilename = URLEncoder.encode(filename, "UTF-8");
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodedFilename);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            // headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
            LOGGER.info("下载文件："+uploadPath+"/"+filePath);
            return ResponseEntity.ok()
                   .headers(headers)
                   .contentLength(safeFile.length())
                   .contentType(MediaType.APPLICATION_OCTET_STREAM)
                   .body(resource);
        }
        return ResponseEntity.notFound().build();
    }



    // 删除文件接口
    @GetMapping("/deletefile/**")
    public Object deleteFile(HttpServletRequest request) {
        String fullPath = request.getRequestURI();
        String filePath = fullPath.substring("/deletefile/".length());
        try {
                filePath = URLDecoder.decode(filePath, "UTF-8");
            } catch (java.io.UnsupportedEncodingException e) { 
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        String uploadPath = System.getProperty("user.dir") + File.separator + "uploads";
        File safeFile = getSafeFile(uploadPath, filePath);
        if (safeFile.isDirectory()) {
            File directory1 = new File(uploadPath + File.separator + filePath);
            deleteDirectory(directory1);
            return ResponseEntity.ok("目录删除成功,稍后查看结果");
            }
           
        if (safeFile != null && safeFile.exists() ) {

            if (safeFile.delete()) {
                return ResponseEntity.ok("文件删除成功,稍后查看结果");
            } else {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件删除失败");
            }
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("文件未找到");
        }
    }


    public static boolean deleteDirectory(File directory) {
        if (directory.exists()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file);
                    } else {
                        file.delete();
                    }
                }
            }
        }
        return directory.delete();
    }
}
